java定时器及利用redis加锁应对分布式

1、利用spring编写定时任务

@Component
@Configurable
@EnableScheduling //关键注解  
public class TimerScheduler {
   @Scheduled(cron = "0 0 0-23 * * ?") //时间表达式,每天整点执行
   public void emailPushByCron(){
      System.out.printIn(“定时任务”);
   }
}

2、利用javaScheduledExecutorService

@Component
public class TimerUtil {
   Private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

   @PostConstruct   //项目启动便调用
   public void PostConstruct() {
      final Runnable beeper = new Runnable() {
         public void run() {
            System.out.println(“定时任务”);
         }
      };
   scheduler.scheduleAtFixedRate(beeper, 10, 60 * 60, SECONDS);
   }
}
3、Redis用于分布式锁

实现思想:

· 获取锁的时候,创建一个key值加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为机器ip,通过此可以判断出锁是被谁创建的。

· 释放锁的时候,通过ip判断是不是该锁,若是该锁,则执行delete进行锁释放。

实例如下:

@Component
@Configurable
@EnableScheduling
public class TimerScheduler {

    private static final String LOCK_SUCCESS = "OK";
    private static final Long RELEASE_SUCCESS = 1L;
    private static final long DEFAULT_EXPIRE = 20000;//超时时间 20s

    @Autowired
    RedisRepository redisRepository

    private static Logger logger = LoggerFactory.getLogger(TimerScheduler.class);

@Scheduled(cron = "0 0 0-23 * * ?")
public void emailPushByCron() {
  String ip = this.getAddressIp(); // 获取本机ip
  String key = "lock-scheduler";
  /**
   * redisRepository.set(key, ip, nxxx, expx, time)
   * key:我们使用key来当锁,保持整个项目是唯一的 
   * ip:value值,表明当前占用锁的是哪一台机器
   * nxxx:我们填的是NX,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作
   * expx:我们传的是PX,意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定 
   * time:过期时间
   */
   String result = redisRepository.set(key, ip, "NX", "PX", DEFAULT_EXPIRE);
   if (LOCK_SUCCESS.equals(result)) {// 拿到锁,拥有执行权限
     try {
       logger.info("start execute...");
       System.out.println(“定时任务”);
       logger.info("scheduler finished...");
     } finally { // 释放锁
        // 定义Lua脚本代码,确保操作是原子性的,获取锁对应的value值,检查是否与ip相等,如果相等则删除锁
         String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
         // jedis.eval()方法,执行Lua脚本,使参数KEYS[1]赋值为key,ARGV[1]赋值为ip
         Object unlockResult = redisRepository.eval(script, Collections.singletonList(key), Collections.singletonList(ip));
         if (RELEASE_SUCCESS.equals(unlockResult)) {
             logger.info("unlock success...");
         } else {
             logger.info("unlock failed...");
         }
     }
  } else { // 没拿到锁
     // 查看当前锁是被谁占用
     String lockIp = redisRepository.get(key);
     logger.info("scheduler lock ip : {}", lockIp);
  }
}

//获取ip地址
private String getAddressIp() {
  try {
    InetAddress addr = InetAddress.getLocalHost();
    String ip = addr.getHostAddress().toString(); // 获取本机ip
    return ip;
  } catch (Exception e) {
    // TODO: handle exception
    return null;
  }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中实现Redis可以使用Redisson框架。Redisson是一个基于Redis分布式Java对象和服务框架,它提供了一系列的分布式实现。 下面是一个使用Redisson实现Redis的示例代码: ```java import org.redisson.Redisson; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.redisson.config.Config; public class RedisLockExample { public static void main(String[] args) { // 创建Redisson配置 Config config = new Config(); config.useSingleServer().setAddress("redis://127.0.0.1:6379"); // 创建Redisson客户端 RedissonClient redisson = Redisson.create(config); // 获取对象 RLock lock = redisson.getLock("myLock"); try { // 尝试,最多等待10秒,自动释放时间为30秒 boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS); if (isLocked) { // 成功获取到,执行业务逻辑 System.out.println("获取到,执行业务逻辑"); } else { // 获取失败 System.out.println("获取失败"); } } catch (InterruptedException e) { e.printStackTrace(); } finally { // 释放 lock.unlock(); } // 关闭Redisson客户端 redisson.shutdown(); } } ``` 上述代码中,首先创建了一个Redisson配置对象,并指定了连接的Redis地址。然后通过Redisson.create方法创建了Redisson客户端。接着使用getLock方法获取了一个对象,的名称为"myLock"。在try块中使用tryLock方法尝试,如果成功获取到,则执行业务逻辑;如果获取失败,则输出获取失败的信息。最后在finally块中释放,并关闭Redisson客户端。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值